package com.mybatis.plug.interceptor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.mybatis.plug.slicingStrategy.SlicingUtil;
import com.mybatis.plug.slicingStrategy.StrategyManager;
import com.mybatis.plug.util.ApplicationContextUtil;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
        @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})})
public class TableSlicingInterceptor implements Interceptor {
    //bean注入
    private static StrategyManager strategyManager;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        boolean junit = ObjectUtil.isNull(ApplicationContextUtil.getContext());
        if (!junit) {
            if (ObjectUtil.isNull(strategyManager)) {
                strategyManager = (StrategyManager) ApplicationContextUtil.getContext().getBean("strategyManager");
            }
        }

        Object target = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaStatementHandler = SystemMetaObject.forObject(target);
/*
        Object parameterObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");
        Object parameterObject2 = metaStatementHandler.getValue("delegate.boundSql.sql");
        Object parameterObject3 = metaStatementHandler.getValue("delegate.boundSql");
        Object parameterObject4 = metaStatementHandler.getValue("delegate.mappedStatement");*/

        doSlicingTable(metaStatementHandler);
        // 传递给下一个拦截器处理
        return invocation.proceed();

    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }

    /**
     * slicing table
     *
     * @param metaStatementHandler
     * @throws ClassNotFoundException
     */
    private void doSlicingTable(MetaObject metaStatementHandler) throws ClassNotFoundException {
        String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
        //分表处理后的sql
        String convertedSql = null;

        if (originalSql != null && !originalSql.equals("")) {
            convertedSql = SlicingUtil.dealSqlByStrategy(originalSql, strategyManager);
            if (StrUtil.isNotBlank(convertedSql)) {
                metaStatementHandler.setValue("delegate.boundSql.sql", convertedSql);
            }
        }
    }
}
